package org.shadow;

import net.e175.klaus.solarpositioning.AzimuthZenithAngle;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.junit.Test;
import org.velocity.SpaUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;

/**
 * ClassName: demo
 * Package: org.shadow
 * Description:
 *
 * @Author BuTang
 * @Create 2023/12/6 14:24
 * @Version 1.0
 */
public class calc {

    double latitude = 30.23800;
    double longitude = 120.13431;
    double elevation = 10;
    double pressure = 1000;
    double temperature = 5;
    String zoneIdName = "Asia/Shanghai";
    ZoneId zoneId = ZoneId.of("Asia/Shanghai");

    /**
     * 设置吸热塔的坐标（暂时用不着）
     */
    double HOLDER_X = 0;
    double HOLDER_Y = 0;
    double HOLDER_Z = 80;

    //使用向量方式计算
    @Test
    public void calc2() throws Exception {

        double h = 100 ;
        double l = 100 ;
        double e = 100 ;

        //设定镜子的坐标为(0,0,0),熔盐塔在镜子的右前方
        //定义熔盐塔坐标为(l,0,h)
        double[] holerd = {l,e,h};
        double a = Math.sqrt(l*l+e*e);
        double b = Math.sqrt(a*a+h*h);
        double[] holerd1 = {l/b,e/b,h/b};

        double sqrt = Math.sqrt(holerd1[0] * holerd1[0] + holerd1[1] * holerd1[1]);
        double sqrt1 = Math.sqrt(sqrt * sqrt + holerd1[2] * holerd1[2]);

        //使用spa计算太阳高度角/方位角
        LocalDateTime localDateTime = LocalDateTime.now();
        AzimuthZenithAngle result =SpaUtils.getAzimuthAndZenithAngle(localDateTime, zoneId, latitude, longitude, elevation, pressure, temperature);
        double highAngle = 90 - result.getZenithAngle() ;
        double highAngleRadians = Math.toRadians(highAngle);

        //取出方位角
        double azimuth = result.getAzimuth();
        double azimuthRadians = Math.toRadians(azimuth);


        //太阳入射向量在地面上的投影
        double shineGroud = h / Math.cos(highAngleRadians);
        //太阳向量的长度
        double L = h/Math.sin(highAngleRadians);

        //shine 的index012分别为xyz
        double[] shine = new double[3];
        shine[2] = h/L ;

        if (azimuthRadians == Math.PI/2 | azimuthRadians == 3*Math.PI/2){
            shine[0] = h/Math.tan(highAngleRadians)/L ;
            shine[1] = 0 ;
        } else if (azimuthRadians == Math.PI |azimuthRadians == 2*Math.PI ) {
            shine[0] = 0 ;
            shine[1] = h/Math.tan(highAngleRadians)/L ;
        } else {
            shine[0] = shineGroud * Math.sin(azimuthRadians)/L;
            shine[1] = shineGroud * Math.cos(azimuthRadians)/L;
        }

            double[] test = shine;
            System.out.println(test);

        //入射光线和反射光线的夹角
        double d = holerd1[0]*shine[0]+holerd1[1]*shine[1]+holerd1[2]*shine[2];
        double acos = Math.toDegrees(Math.acos(d));

        //取出镜子的法线
        double[] faxian = {holerd1[0]+shine[0],holerd1[1]+shine[1],holerd1[2]+shine[2]};

        //法线与地面的夹角
        double sqrt2 = Math.sqrt(faxian[0] * faxian[0] + faxian[1] * faxian[1]);
        double v = faxian[2] / sqrt2;
        double atan = Math.atan(v);
        System.out.println("镜面与地面的夹角"+(90 - Math.toDegrees(atan)));

        double a1 = -faxian[0] / faxian[1];
        double atan1 = Math.atan(a1);
        System.out.println("定日镜的方位角为"+(Math.toDegrees(atan1)));

    }



    /**
     * 计算镜场南方的镜子高度角
     * @throws Exception
     */
    @Test
    public void test1() throws Exception {
        LocalDateTime localDateTime = LocalDateTime.now();
        AzimuthZenithAngle result =SpaUtils.getAzimuthAndZenithAngle(localDateTime, zoneId, latitude, longitude, elevation, pressure, temperature);

        //高度角
        double eleAngle = 90 - result.getZenithAngle();
        System.out.println("此时太阳高度角为："+eleAngle+"°");

        /**
         * 正南方向定日镜高度角
         * 吸热塔方向为正
         */

        //吸热塔高度
        double TOWER_HIGH = 80 ;
        //定日镜与吸热塔的距离
        double DISTANCE = 120 ;
        //定日镜支架高度
        double HOLDER_HIGHT = 1.5 ;
        //镜子宽度
        double MIRROR_WIDE = 1.0 ;

        //定日镜与吸热塔所形成的角的tan值
        double tan = (TOWER_HIGH - HOLDER_HIGHT) / DISTANCE;
        //定日镜与吸热塔所形成的角度
        double angleDegrees = Math.toDegrees(Math.atan(tan));
        //入射光线和法线的夹角
        double a = (180-eleAngle-angleDegrees)/2;
        double mirrorHigh = (180-2*a)/2-eleAngle;
        System.out.println(mirrorHigh);

        //支架+镜子总高度
        double h = HOLDER_HIGHT + MIRROR_WIDE * Math.sin(Math.toRadians(mirrorHigh));

        //定义在在定日镜安装位置XYZ坐标为 (0,0,0)
        //定日镜镜子四个角坐标：N表示北方，S表示南方，L表示左，R表示右

        //镜子在垂直方向上的高度
        double h1 =Math.sin(Math.toRadians(mirrorHigh))*(MIRROR_WIDE/2) ;
        double w1 = MIRROR_WIDE/2 ;

        //NL(-w1,w1,HOLDER_HIGHT-h1)
        //NR(w1,w1,HOLDER_HIGHT-h1)
        //SL(-w1,-w1,HOLDER_HIGHT+h1)
        //NR(w1,-w1,HOLDER_HIGHT+h1)
        double Nl = (HOLDER_HIGHT-h1)/Math.tan(Math.toRadians(eleAngle));
        double Sl = (HOLDER_HIGHT+h1)/Math.tan(Math.toRadians(eleAngle));

        //影子在地上的坐标
        //NL(-w1,w1+Nl,0)
        //NR(w1,w1+Nl,0)
        //SL(-w1,-w1+Sl,0)
        //NR(w1,-w1+Sl,0)



        double azimuth = result.getAzimuth();
        double mirrorAzimuth = 0;
        /**
         * 正南方向的定日镜的方位角
         */
        if (azimuth > 180){
        double angle1 = 360 - azimuth ;
        double included = (180 - angle1) /2 ;
        mirrorAzimuth = 90 - 2 * included ;
        System.out.println(mirrorAzimuth);
        }else {
            mirrorAzimuth = azimuth - 90;
            System.out.println(mirrorAzimuth);
        }

        /**
         * 计算西侧(右侧),早上时的定日镜的方位角
         */
        //计算定日镜与吸热塔形成的夹角
        double n = 100 ;
        double e = 100 ;
        double β = Math.toDegrees (Math.atan(n / e));

        //Y轴与入射光线形成的夹角
        double α = 180 - azimuth ;

        //入射光线和镜面形成的夹角
        double v = (180 - (α + 90 + β))/2;

        //镜面与X轴形成的夹角
        double angle2 = β + v ;
        System.out.println("南方，西侧定日镜，方位角<180时，此时的方位角为："  + angle2 );

        /**
         * 太阳 180°<方位角<270° 时
         * 计算西侧(右侧),下午的定日镜的方位角
         */
        double angle3 = 270 - result.getAzimuth();

        /**
         * 太阳 270°<方位角<360° 时
         * 计算西侧(右侧)下午的定日镜的方位角
         */
        double angle4 = 90 -((90-(result.getAzimuth()-270)*2)/2 + result.getAzimuth() -270);

        /**
         * 太阳 0°<方位角<90° 时
         * 计算西侧(右侧)的定日镜的方位角
         */
        //计算定日镜与吸热塔形成的夹角
        double n1 = 100 ;
        double e1 = 100 ;
        double γ =  Math.toDegrees(Math.atan(n1/e1));

        double a1 = 90-((90-γ+result.getAzimuth())/2 + (90-result.getAzimuth()));


      }
}

































